﻿#include "imagedisplay.h"
#include <QPen>
#include <QColor>
#include <QDebug>
#include <QPainter>

const int MAX_IMAGE_SIZE_X = 5000;
const int MAX_IMAGE_SIZE_Y = 5000;
const int DEFAULT_IMAGE_SIZE_X = 1600;
const int DEFAULT_IMAGE_SIZE_Y = 1200;

struct rgb24
{
    unsigned char b;
    unsigned char g;
    unsigned char r;
};

ImageDisplay::ImageDisplay(QWidget *parent) :
        QWidget(parent),
        m_size(DEFAULT_IMAGE_SIZE_X, DEFAULT_IMAGE_SIZE_Y),
        m_zoomFactor(1.0),
        m_image_count(0),
        m_showCross(true)
{
    setMaximumSize( QSize( MAX_IMAGE_SIZE_X, MAX_IMAGE_SIZE_Y ) );
    m_image = QImage( m_size, QImage::Format_RGB32 );
    m_image.fill( Qt::darkGray );
    setFixedSize( m_size * m_zoomFactor );
    update();
}

ImageDisplay::~ImageDisplay()
{

}
QImage ImageDisplay::getImage()
{
    QImage image;
    m_image_mutex.lock();
    image = m_image.copy();
    m_image_mutex.unlock();
    return image;
}

void ImageDisplay::test()
{
    //只用来测试
    static char c = 0;
	m_image_mutex.lock();
    int width = m_image.width();
    int height = m_image.height();
	
    for (int i = 0; i < height; i++)
    {
        QRgb *line = (QRgb *)m_image.scanLine(i);
        for (int j = 0; j < width; j ++)
        {
            line[j] = qRgb(c, c, c);
        }
        c++;
    }
	m_image_mutex.unlock();
    c++;
}

void ImageDisplay::fillImage(QRgb color)
{
    m_image_mutex.lock();
    m_image.fill(color);
    m_image_mutex.unlock();
    update();
}

void ImageDisplay::fillImage(const QColor color)
{
    m_image_mutex.lock();
    m_image.fill(color);
    m_image_mutex.unlock();
    update();
}

void ImageDisplay::fillImage(Qt::GlobalColor color)
{
    m_image_mutex.lock();
    m_image.fill(color);
    m_image_mutex.unlock();
    update();
}

bool ImageDisplay::loadImage(const QString &fileName)
{
    bool ok;
    m_image_mutex.lock();
    ok = m_image.load(fileName);
    //m_image = m_image.convertToFormat(QImage::Format_RGB32);
    m_image_mutex.unlock();
    if (ok)
    {
        setSize(m_image.size());
    }
    qDebug() <<  "ImageDisplay::loadImage = " << ok;
    return ok;
}

bool ImageDisplay::saveImage( const QString &fileName )
{
    m_image_mutex.lock();
    QImage image = m_image.copy();
    m_image_mutex.unlock();
    return image.save(fileName);
}

void ImageDisplay::setRGB24Image(const unsigned char *imgBuf, QSize size)
{
    int imageWidth = size.width();
    int imageHeight = size.height();
    setSize(size);
	m_image_mutex.lock();
    int X = qMin(imageWidth, m_size.width());
    int Y = qMin(imageHeight, m_size.height());  
    for (int row = 0; row < Y; row++)
    {
        QRgb *line = (QRgb *)m_image.scanLine(row);
        // 找到 CCD 数据一行的开头位置，一个像素占3字节
        rgb24 * pixel = (rgb24 *) &imgBuf[3 * row * imageWidth];
        for (int col = 0; col < X; col ++)
        {
            line[col] = qRgb(pixel[col].r, pixel[col].g, pixel[col].b);
        }
    }
    m_image_count++;
    m_image_mutex.unlock();
    update();
}

void ImageDisplay::setRGB32Image(const unsigned char *imgBuf, QSize size)
{
    int imageWidth = size.width();
    int imageHeight = size.height();
    setSize(size);
	m_image_mutex.lock();
    int X = qMin(imageWidth, m_size.width());
    int Y = qMin(imageHeight, m_size.height());
    for (int row = 0; row < Y; row++)
    {
        QRgb * line = (QRgb *)m_image.scanLine(row);
        // 找到 CCD 数据一行的开头位置，一个像素占3字节
        QRgb * pixel = (QRgb *) &imgBuf[4 * row * imageWidth];
        for (int col = 0; col < X; col ++)
        {
            line[col] = pixel[col];
        }
    }
    m_image_count++;
    m_image_mutex.unlock();
    update();
}

void ImageDisplay::setMono8Image(const unsigned char *imgBuf, QSize size)
{

    int imageWidth = size.width();
    int imageHeight = size.height();
    setSize(size);
    m_image_mutex.lock();
    int X = qMin(imageWidth, m_size.width());
    int Y = qMin(imageHeight, m_size.height());
    for (int row = 0; row < Y; row++)
    {
        QRgb *line = (QRgb *)m_image.scanLine(row);
        // 找到 CCD 数据一行的开头位置，一个像素占3字节
        unsigned char * pixel = (unsigned char *) &imgBuf[row * imageWidth];
        for (int col = 0; col < X; col ++)
        {
            line[col] = qRgb(pixel[col], pixel[col], pixel[col]);
        }
    }
    m_image_count++;
    m_image_mutex.unlock();
    update();
}

void ImageDisplay::setImage(const QImage &image)
{
    // TODO: 这里的代码有待完善
    m_image_mutex.lock();
    m_image = image;
    m_image_mutex.unlock();
    setSize( image.size() );
    m_image_count++;
    update();
}

void ImageDisplay::setSize(QSize size)
{
    m_size.setWidth(qBound(1, size.width(), MAX_IMAGE_SIZE_X));
    m_size.setHeight(qBound(1, size.height(), MAX_IMAGE_SIZE_Y));
	
	m_image_mutex.lock();
    if ( m_image.size() != size )
    {   
        m_image = QImage(m_size, QImage::Format_RGB32);
        m_image.fill(Qt::darkGray);
        setFixedSize(m_size * m_zoomFactor);
    }
	m_image_mutex.unlock();
}

void ImageDisplay::setZoomFactor(double factor)
{
    m_zoomFactor = factor;
    setFixedSize(m_size * m_zoomFactor);
    update();
}

void ImageDisplay::setZoomFactorPCT(int factor)
{
    m_zoomFactor = factor / 100.0;
    setFixedSize(m_size * m_zoomFactor);
    update();
}

void ImageDisplay::showCross(bool show)
{
    m_showCross = show;
    update();
}

inline void ImageDisplay::drawImage(QPainter &painter)
{
    painter.save();
    painter.scale(m_zoomFactor, m_zoomFactor);
    m_image_mutex.lock();
    painter.drawImage ( 0, 0, m_image);
    m_image_mutex.unlock();
    painter.restore();
}

inline void ImageDisplay::drawCross(QPainter &painter)
{
    int mid_x = size().width() / 2;
    int mid_y = size().height() / 2;
    QPen pen(Qt::red);
    pen.setWidth(2);
    pen.setStyle(Qt::SolidLine);
    painter.setPen(pen);
    painter.drawLine(mid_x - 50, mid_y, mid_x + 50, mid_y);
    painter.drawLine(mid_x, mid_y - 50, mid_x, mid_y + 50);
    pen.setColor(Qt::black);
    painter.setPen(pen);
    painter.drawRect ( rect() );
}

void ImageDisplay::paintEvent( QPaintEvent * event )
{
    (void) event;
    QPainter painter(this);
    painter.setRenderHint ( QPainter::Antialiasing, true );
    drawImage(painter);
    if (m_showCross)
    {
        drawCross(painter);
    }
}

